﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.AccessControl;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace FastGPT_Admin.Tool
{
    /// <summary>
    /// AES加解密字符串
    /// </summary>
    internal class AESCryptoTextProvider
    {
        #region 方法

        /// <summary>
        /// 加密
        /// IV等于Key且Key和IV将被转换为MD5值
        /// </summary>
        /// <param name="key">密钥</param>
        /// <param name="sourceText">原文</param>
        /// <returns>密文(Base64字符串)</returns>
        public static string Encrypt(string key, string sourceText)
        {
            return Encrypt(key, key, sourceText);
        }

        /// <summary>
        /// 加密
        /// Key和IV将被转换为MD5值
        /// </summary>
        /// <param name="key">密钥</param>
        /// <param name="IV">初始化向量</param>
        /// <param name="sourceText">原文</param>
        /// <returns>密文(Base64字符串)</returns>
        public static string Encrypt(string key, string IV, string sourceText)
        {
            if (key == null)
                throw new ArgumentNullException(nameof(key));
            if (IV == null)
                throw new ArgumentNullException(nameof(IV));
            if (sourceText == null)
                throw new ArgumentNullException(nameof(sourceText));

            using (SHA512 sha512 = SHA512.Create())
            {
                return Convert.ToBase64String(Encrypt(sha512.ComputeHash(System.Text.Encoding.UTF8.GetBytes(key)), sha512.ComputeHash(System.Text.Encoding.UTF8.GetBytes(IV)), sourceText));
            }
        }

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="rgbKey">密钥</param>
        /// <param name="rgbIV">初始化向量</param>
        /// <param name="sourceText">原文</param>
        /// <returns>密文</returns>
        public static byte[] Encrypt(byte[] rgbKey, byte[] rgbIV, string sourceText)
        {
            if (rgbKey == null)
                throw new ArgumentNullException(nameof(rgbKey));
            if (rgbIV == null)
                throw new ArgumentNullException(nameof(rgbIV));
            if (sourceText == null)
                throw new ArgumentNullException(nameof(sourceText));

            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (Aes aes = Aes.Create())
                using (ICryptoTransform transform = aes.CreateEncryptor(rgbKey, rgbIV))
                using (CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write))
                using (StreamWriter streamWriter = new StreamWriter(cryptoStream))
                {
                    streamWriter.Write(sourceText);
                    streamWriter.Flush();
                }

                return memoryStream.ToArray();
            }
        }

        /// <summary>
        /// 解密
        /// IV等于Key且Key和IV将被转换为MD5值
        /// </summary>
        /// <param name="key">密钥</param>
        /// <param name="cipherText">密文(Base64字符串)</param>
        /// <returns>原文</returns>
        public static string Decrypt(string key, string cipherText)
        {
            return Decrypt(key, key, cipherText);
        }

        /// <summary>
        /// 解密
        /// Key和IV将被转换为MD5值
        /// </summary>
        /// <param name="key">密钥</param>
        /// <param name="IV">初始化向量</param>
        /// <param name="cipherText">密文(Base64字符串)</param>
        /// <returns>原文</returns>
        public static string Decrypt(string key, string IV, string cipherText)
        {
            if (key == null)
                throw new ArgumentNullException(nameof(key));
            if (IV == null)
                throw new ArgumentNullException(nameof(IV));
            if (cipherText == null)
                throw new ArgumentNullException(nameof(cipherText));

            using (SHA512 sha512 = SHA512.Create())
            {
                return Decrypt(sha512.ComputeHash(System.Text.Encoding.UTF8.GetBytes(key)), sha512.ComputeHash(System.Text.Encoding.UTF8.GetBytes(IV)), Convert.FromBase64String(cipherText));
            }
        }

        /// <summary>
        /// 解密
        /// IV等于Key
        /// </summary>
        /// <param name="key">密钥</param>
        /// <param name="cipherBuffer">密文</param>
        /// <returns>原文</returns>
        public static string Decrypt(string key, byte[] cipherBuffer)
        {
            return Decrypt(key, key, cipherBuffer);
        }

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="key">密钥</param>
        /// <param name="IV">初始化向量</param>
        /// <param name="cipherBuffer">密文</param>
        /// <returns>原文</returns>
        public static string Decrypt(string key, string IV, byte[] cipherBuffer)
        {
            if (key == null)
                throw new ArgumentNullException(nameof(key));
            if (IV == null)
                throw new ArgumentNullException(nameof(IV));
            if (cipherBuffer == null)
                throw new ArgumentNullException(nameof(cipherBuffer));

            using (SHA512 sha512 = SHA512.Create())
            {
                return Decrypt(sha512.ComputeHash(System.Text.Encoding.UTF8.GetBytes(key)), sha512.ComputeHash(System.Text.Encoding.UTF8.GetBytes(IV)), cipherBuffer);
            }
        }

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="rgbKey">密钥</param>
        /// <param name="rgbIV">初始化向量</param>
        /// <param name="cipherBuffer">密文</param>
        /// <returns>原文</returns>
        public static string Decrypt(byte[] rgbKey, byte[] rgbIV, byte[] cipherBuffer)
        {
            if (rgbKey == null)
                throw new ArgumentNullException(nameof(rgbKey));
            if (rgbIV == null)
                throw new ArgumentNullException(nameof(rgbIV));
            if (cipherBuffer == null)
                throw new ArgumentNullException(nameof(cipherBuffer));

            using (MemoryStream stream = new MemoryStream(cipherBuffer))
            {
                return Decrypt(rgbKey, rgbIV, stream);
            }
        }

        /// <summary>
        /// 解密
        /// IV等于Key
        /// </summary>
        /// <param name="key">密钥</param>
        /// <param name="cipherStream">密文</param>
        /// <returns>原文</returns>
        public static string Decrypt(string key, Stream cipherStream)
        {
            return Decrypt(key, key, cipherStream);
        }

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="key">密钥</param>
        /// <param name="IV">初始化向量</param>
        /// <param name="cipherStream">密文</param>
        /// <returns>原文</returns>
        public static string Decrypt(string key, string IV, Stream cipherStream)
        {
            if (key == null)
                throw new ArgumentNullException(nameof(key));
            if (IV == null)
                throw new ArgumentNullException(nameof(IV));
            if (cipherStream == null)
                throw new ArgumentNullException(nameof(cipherStream));

            using (SHA512 sha512 = SHA512.Create())
            {
                return Decrypt(sha512.ComputeHash(System.Text.Encoding.UTF8.GetBytes(key)), sha512.ComputeHash(System.Text.Encoding.UTF8.GetBytes(IV)), cipherStream);
            }
        }

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="rgbKey">密钥</param>
        /// <param name="rgbIV">初始化向量</param>
        /// <param name="cipherStream">密文</param>
        /// <returns>原文</returns>
        public static string Decrypt(byte[] rgbKey, byte[] rgbIV, Stream cipherStream)
        {
            if (rgbKey == null)
                throw new ArgumentNullException(nameof(rgbKey));
            if (rgbIV == null)
                throw new ArgumentNullException(nameof(rgbIV));
            if (cipherStream == null)
                throw new ArgumentNullException(nameof(cipherStream));

            using (Aes aes = Aes.Create())
            using (ICryptoTransform transform = aes.CreateDecryptor(rgbKey, rgbIV))
            using (CryptoStream cryptoStream = new CryptoStream(cipherStream, transform, CryptoStreamMode.Read))
            using (StreamReader streamReader = new StreamReader(cryptoStream))
            {
                return streamReader.ReadToEnd();
            }
        }
        #endregion

        /// <summary>
        /// AES 算法加密(ECB模式) 将明文加密，加密后进行base64编码，返回密文
        /// </summary>
        /// <param name="EncryptStr">明文</param>
        /// <param name="Key">密钥</param>
        /// <returns>加密后base64编码的密文</returns>
        public static string AesEncryptor_Base64(string EncryptStr, string Key)
        {
            try
            {
                //byte[] keyArray = Encoding.UTF8.GetBytes(Key);
                byte[] keyArray = Convert.FromBase64String(Key);
                byte[] toEncryptArray = Encoding.UTF8.GetBytes(EncryptStr);

                RijndaelManaged rDel = new RijndaelManaged();
                rDel.Key = keyArray;
                rDel.Mode = CipherMode.ECB;
                rDel.Padding = PaddingMode.PKCS7;

                ICryptoTransform cTransform = rDel.CreateEncryptor();
                byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

                return Convert.ToBase64String(resultArray, 0, resultArray.Length);
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// AES 算法解密(ECB模式) 将密文base64解码进行解密，返回明文
        /// </summary>
        /// <param name="DecryptStr">密文</param>
        /// <param name="Key">密钥</param>
        /// <returns>明文</returns>
        public static string AesDecryptor_Base64(string DecryptStr, string Key)
        {
            try
            {
                //byte[] keyArray = Encoding.UTF8.GetBytes(Key);
                byte[] keyArray = Convert.FromBase64String(Key);
                byte[] toEncryptArray = Convert.FromBase64String(DecryptStr);

                RijndaelManaged rDel = new RijndaelManaged();
                rDel.Key = keyArray;
                rDel.Mode = CipherMode.ECB;
                rDel.Padding = PaddingMode.PKCS7;

                ICryptoTransform cTransform = rDel.CreateDecryptor();
                byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

                return Encoding.UTF8.GetString(resultArray);//  UTF8Encoding.UTF8.GetString(resultArray);
            }
            catch (Exception ex)
            {
                return null;
            }
        }
    }
}
